#include <stdio.h>
#include "..\include\imp_typedefine.h"
#include "..\include\imp_io_wrapper.h"
#include "..\include\imp_os_wrapper.h"
#include <windows.h>

typedef struct _t_ime_locker
{
	ImpBool binary;
	void *inst;
}t_ime_locker;

typedef struct _t_ime_taskid
{
	void * handle;
	Int32 id;
}t_ime_taskid;

ImpTaskID impos_task_open(ImpTaskProc *proc, void *param, Int32 prio, Int32 stack_size)
{
	DWORD m_ThreadID;
	Int32 priority;
	t_ime_taskid *task = (t_ime_taskid *)IMP_Malloc( sizeof(t_ime_taskid) );

	HANDLE hThread = CreateThread(0, 0,(LPTHREAD_START_ROUTINE)proc, (void *)param, CREATE_SUSPENDED, &m_ThreadID);

	priority = THREAD_PRIORITY_NORMAL;

	SetThreadPriority(hThread, priority);
	ResumeThread(hThread);
	task->handle = (void *)hThread;
	task->id = m_ThreadID;
	return (ImpTaskID)task;
}

ImpBool impos_task_close(ImpTaskID taskId)
{
	t_ime_taskid *task = (t_ime_taskid *)taskId;
	TerminateThread(task->handle, 0x1);
	IMP_Free( task );
	return IMP_True;
}

ImpBool impos_message_send(ImpTaskID taskId, ImpMessage *msg)
{
	t_ime_taskid *task = (t_ime_taskid *)taskId;
	PostThreadMessage((DWORD)task->id, (UINT)msg->id, (WPARAM)msg->pBuffer, (LPARAM)msg->nSize);
	return IMP_True;
}

ImpBool impos_message_recv(ImpTaskID taskId, ImpMessage *msg)
{
	MSG msg0;
	GetMessage(&msg0, NULL, IMPOS_MsgId_min, IMPOS_MsgId_max);
	msg->id = (e_impos_msgId)msg0.message;
	msg->pBuffer = (void*)msg0.wParam;
	msg->nSize = (Int32)msg0.lParam;
	return IMP_True;
}

ImpBool impos_task_delay(Int32 ms)
{
	::Sleep(ms);
	return IMP_True;
}

ImpLocker impos_lock_open(void)
{
	HANDLE handle = CreateEvent( NULL, FALSE, FALSE, NULL ); // initial lock, auto-lock
	IMP_Assert(handle!=0, "impos_lock_open fail\n");
	return (ImpLocker)handle;
}

ImpBool impos_lock_close(ImpLocker lock)
{
	CloseHandle((HANDLE)lock);
	return IMP_True;
}

ImpBool impos_lock_wait(ImpLocker lock) // infinite
{
	DWORD ret = WaitForSingleObject((HANDLE)lock, INFINITE);
	return IMP_True;
}

ImpBool impos_lock(ImpLocker lock)
{
	ResetEvent((HANDLE)lock);
	return IMP_True;
}

ImpBool impos_unlock(ImpLocker lock)
{
	SetEvent((HANDLE)lock);
	return IMP_True;
}

extern void imewin_relay_call(void *func, void *param);
void impos_relay_call(void *func, void *param)
{
	imewin_relay_call(func, param);
}